package com.chenjun.designpattern.behavior.observer;
import java.util.*;
/**
 * <p>
 * 观察者模式是对象的行为模式，又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
 * 
 * <p>
 * 观察者模式定义了一种一对多的依赖关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时，会通知所有观察者对象，使它们能够自动更新自己。
 * 
 * <p>拉模型
 * @author Administrator
 *
 */
public class 观察者模式2
{
	public static void main(String[] args)
	{
		//new 观察者
		Observer2 observer2 = new ConcreteObserver2();
		//new 主题对象
		AbstractSubject2 subject2 = new ConcreteSubject2();
		//添加观察者
		subject2.addOb(observer2);
		//调用change方法
		((ConcreteSubject2)subject2).change("新状态");
	}
}

/**
 * 抽象主题2 （抽象被观察者2）
 * @author Administrator
 *
 */
abstract class AbstractSubject2
{
	private Set<Observer2> obSet = new HashSet<Observer2>();
	
	public boolean addOb(Observer2 ob2)
	{
		System.out.println("添加一个观察者");
		return obSet.add(ob2);
	}

	public boolean removeOb(Observer2 ob2)
	{
		System.out.println("移除一个观察者");
		return obSet.remove(ob2);
	}
	
	/**
	 * 通知观察者根据this引用更新自己,需要任何字段都可以this.XXX获取
	 */
	public void notifyObserver2()
	{
		for(Observer2 item : obSet)
		{
			item.update(this);
		}
	}
}

/**
 * 具体主题 2（具体被观察者2）
 * @author Administrator
 *
 */
class ConcreteSubject2 extends AbstractSubject2
{
	private String state="旧状态";
	
	public void change(String newState)
	{
		System.out.println("主题【ConcreteSubject2】的 state 已经由【"+ state +"】转换为【"+newState+"】");
		//状态更新
		state = newState; 
		this.notifyObserver2();
	}

	/**
	 * getter and setter
	 * @return
	 */
	public String getState()
	{
		return state;
	}

	public void setState(String state)
	{
		this.state = state;
	}
}

/**
 * 抽象观察者,这里可以是abstract或者interface
 * @author Administrator
 */
interface Observer2
{
	public void update(AbstractSubject2 subject2);
}

/**
 * 具体观察者
 */
class ConcreteObserver2 implements Observer2
{
	private String state="";
	@Override
	public void update(AbstractSubject2 subject2)
	{
		state = ((ConcreteSubject2)subject2).getState();
		//打印观察者变化
		System.out.println("观察者已经获得更新通知--------通知后的状态变为【"+state+"】");
	}
	
	/**
	 * getter and setter
	 * @return
	 */
	public String getState()
	{
		return state;
	}
	
	public void setState(String state)
	{
		this.state = state;
	}
	
}

